const storage = (function () {
  const converter = {
    read(data) {
      if (typeof data === 'string') {
        data = data.replace(/(%[\dA-F]{2})+/gi, decodeURIComponent);
      }
      try {
        return JSON.parse(data) || {};
      } catch (error) {
        return {};
      }
    },
    write(data) {
      return encodeURIComponent(JSON.stringify(data)).replace(
        /%(2[346BF]|3[AC-F]|40|5[BDE]|60|7[BCD])/g,
        decodeURIComponent
      );
    },
  };

  function handleKey(key) {
    return encodeURIComponent(key)
      .replace(/%(2[346B]|5E|60|7C)/g, decodeURIComponent)
      .replace(/[()]/g, decodeURIComponent);
  }

  function handleExpires(option) {
    /*
     * expires：过期时间（为无效值时不过期），类型 Number；
     * unit：过期时间的单位，默认是 day, 可选: month,day,hour,minute
     * */
    let opt = { expires: 7, unit: 'day' };
    let { expires, unit } = Object.assign(opt, option);
    if (typeof expires === 'number' && expires > 0) {
      const ms = { month: 2592e6, day: 864e5, hour: 36e5, minute: 6e4 };
      expires = Date.now() + expires * (ms[unit] || ms.day);
    } else {
      expires = 0;
    }
    return { expires, unit };
  }

  class StorageApi {
    constructor(storage) {
      this.storage = storage;
    }
    setItem(key, value, option) {
      key = handleKey(key);
      option = handleExpires(option);
      this.storage.setItem(key, converter.write({ value, option }));
    }
    getItem(key, defaultValue) {
      key = handleKey(key);
      const { value, option } = converter.read(this.storage.getItem(key));
      // console.log(option);
      if (option && option.expires > 0 && option.expires < Date.now()) {
        this.storage.removeItem(key);
        return defaultValue;
      }
      return value !== undefined ? value : defaultValue;
    }
    removeItem(key) {
      key = handleKey(key);
      this.storage.removeItem(key);
    }
    clear() {
      this.storage.clear();
    }
  }

  return {
    local: new StorageApi(window.localStorage),
    session: new StorageApi(window.sessionStorage),
  };
})();

export default storage;
